package org.github.manx98.jlibhac.common.math;

import cn.hutool.core.util.ByteUtil;

import java.math.BigInteger;
import java.nio.ByteOrder;

/**
 * Uint32
 *
 * @author Manx98
 * @version 1.0
 * @since 2022/10/2 20:36
 */
public class Uint32 extends UnsignedNumber {
    private final long value;

    public Uint32(byte[] val) {
        this(val, 0, ByteOrder.LITTLE_ENDIAN);
    }

    public Uint32(byte[] magnitude, int off, ByteOrder order) {
        this(ByteUtil.bytesToLong(new byte[]{
                magnitude[off],
                magnitude[off + 1],
                magnitude[off + 2],
                magnitude[off + 3],
                0,
                0,
                0,
                0,
        }, 0, order));
    }

    public Uint32(long value) {
        this.value = value & 0xffffffffL;
    }

    @Override
    public UnsignedNumber shiftLeft(int n) {
        return new Uint32(value << n);
    }

    @Override
    public UnsignedNumber shiftRight(int n) {
        return new Uint32(value >> n);
    }

    @Override
    public UnsignedNumber and(UnsignedNumber val) {
        return new Uint32(value & val.intValue());
    }

    @Override
    public UnsignedNumber or(UnsignedNumber val) {
        return new Uint32(value | val.intValue());
    }

    @Override
    public UnsignedNumber xor(UnsignedNumber val) {
        return new Uint32(value ^ val.intValue());
    }

    @Override
    public UnsignedNumber add(UnsignedNumber val) {
        return new Uint32(longValue() + val.longValue());
    }

    @Override
    public byte[] toByteArray(ByteOrder order) {
        byte[] bytes = new byte[4];
        toByteArray(bytes, 0, order);
        return bytes;
    }

    @Override
    public void toByteArray(byte[] result, int offset, ByteOrder byteOrder) {
        int intValue = (int) value;
        if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
            for (int i = 0; i < 4; ++i) {
                result[i] = (byte) ((int) (intValue & 255L));
                intValue >>= 8;
            }
        } else {
            for (int i = 3; i >= 0; --i) {
                result[i] = (byte) ((int) (intValue & 255L));
                intValue >>= 8;
            }
        }
    }

    @Override
    public int intValue() {
        return (int) value;
    }

    @Override
    public long longValue() {
        return value;
    }

    @Override
    public float floatValue() {
        return value;
    }

    @Override
    public double doubleValue() {
        return value;
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }

    public String toString(int radix) {
        return BigInteger.valueOf(value).toString(radix);
    }
}
